package com.example.arithmeticleetcode.leetcode.s2021.july;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;

/**
 * @author fangzhen@focusmedia.cn
 * @creation time 2021/9/10
 */
public class OrderDemo {

//    private static volatile Map<String, GoodsInfo> allGoodsMap;
//    private static volatile Map<String, UserInfo> allUserInfoMap;
    private volatile boolean[] flag = new boolean[14];



    // 创建一个可重用固定个数的线程池
    private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);


    public static void main(String[] args) {
        //初始化商品信息
        List<GoodsInfo> goodsInfos = getGoodsInfos();
        //对获取到的商品信息进行排序
        List<GoodsInfo> sortGoodsList = getSortGoods(goodsInfos);
        sortGoodsList.forEach(goodsInfo -> System.out.println(goodsInfo));
        //建立一个全局的商品信息
//        allGoodsMap = sortGoodsList.stream().collect(Collectors.toConcurrentMap(GoodsInfo::getId, Function.identity()));
        //获取对应所有的用户
        List<UserInfo> userInfos = getUserInfos();
        //跟据用户进行分组
        List<UserInfo> sortUserInfos = getSortUserInfos(userInfos);
        sortUserInfos.forEach(userInfo -> System.out.println(userInfo));
        //建立一个全局的用户信息
//        allUserInfoMap = sortUserInfos.stream().collect(Collectors.toConcurrentMap(UserInfo::getId, Function.identity()));
        int goodsCount = sortGoodsList.size();
        int userInfoCount = sortUserInfos.size();
        int divide = (int) Math.floor(goodsCount / userInfoCount);

        for (int i = 0; i < userInfoCount; i++) {
            final int tempI = i;
            UserInfo userInfo = sortUserInfos.get(tempI);
            fixedThreadPool.execute(() -> {
                CountDownLatch countDownLatch = new CountDownLatch(1);

                int l = divide * tempI;
                int r = l + divide;
                CountDownLatch await = new CountDownLatch(divide);
//                int flagIndex = 0;
//                while (flagIndex < l) {
//                    if (!flag[flagIndex++]) {
//                        l = flagIndex;
//                        System.out.println(Arrays.toString(flag) + "----l===" + l);
//                        break;
//                    }
//                }
//                System.out.println(Arrays.toString(flag));
                System.out.println("userInfo" + Thread.currentThread().getName() + "" + userInfo.getId());
                System.out.println("l " + l + ": r" + r);
                while (l < r && l < goodsCount) {
//                    if (flag[l]) {
//                        continue;
//                    }
                    final int idx = l++;
                    fixedThreadPool.execute(() -> {
                        try {
                            countDownLatch.await();
                            GoodsInfo goodsInfo = sortGoodsList.get(idx);
                            await.countDown();
                        } catch (Exception e) {

                        }
                    });
                    GoodsInfo goodsInfo = sortGoodsList.get(l++);
//                    if (!allGoodsMap.containsKey(goodsInfo.id)) {
//                        System.out.println(goodsInfo.getId() + " : goodsInfo已经被抢");
//                        continue;
//                    }
                    System.out.println("userInfo" + Thread.currentThread().getName() + "" + userInfo.getId());
                    try {
                        Thread.sleep(2000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
//                    flag[l] = true;
//                    System.out.println("l=====" + l + " flag ============" + flag[l]);
                    //抢到
                    if (true) {
//                        System.out.println("allGoodsMap" + allGoodsMap.get(goodsInfo.getId()));
                        System.out.println(userInfo.getId() + ": userInfo被删除 " + goodsInfo.getId() + " : goodsInfo被删除");
//                        allGoodsMap.remove(goodsInfo.getId());
//                        allUserInfoMap.remove(userInfo.getId());
                        break;
                    } else {
                        //抢不到
                        r = r << 1;
                    }
                }
                countDownLatch.countDown();
                try {
                    await.await();
                    //查数据表
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        fixedThreadPool.shutdown();

    }

    private static List<GoodsInfo> getGoodsInfos() {
        GoodsInfo goodsInfo1 = new GoodsInfo("1", BigDecimal.valueOf(2.2), true);
        GoodsInfo goodsInfo2 = new GoodsInfo("2", BigDecimal.valueOf(3.5), true);
        GoodsInfo goodsInfo3 = new GoodsInfo("3", BigDecimal.valueOf(4.4), true);
        GoodsInfo goodsInfo4 = new GoodsInfo("4", BigDecimal.valueOf(4.5), false);
        GoodsInfo goodsInfo5 = new GoodsInfo("5", BigDecimal.valueOf(3.4), true);
        GoodsInfo goodsInfo6 = new GoodsInfo("6", BigDecimal.valueOf(6.4), true);
        GoodsInfo goodsInfo7 = new GoodsInfo("7", BigDecimal.valueOf(5.3), true);
        GoodsInfo goodsInfo8 = new GoodsInfo("8", BigDecimal.valueOf(5.2), true);
        GoodsInfo goodsInfo9 = new GoodsInfo("9", BigDecimal.valueOf(6.1), true);
        GoodsInfo goodsInfo10 = new GoodsInfo("10", BigDecimal.valueOf(6.3), true);
        GoodsInfo goodsInfo11 = new GoodsInfo("11", BigDecimal.valueOf(7.2), true);
        GoodsInfo goodsInfo12 = new GoodsInfo("12", BigDecimal.valueOf(7.1), true);
        GoodsInfo goodsInfo13 = new GoodsInfo("13", BigDecimal.valueOf(7.0), true);
        List<GoodsInfo> list = new ArrayList<>();
        list.add(goodsInfo1);
        list.add(goodsInfo2);
        list.add(goodsInfo3);
        list.add(goodsInfo4);
        list.add(goodsInfo5);
        list.add(goodsInfo6);
        list.add(goodsInfo7);
        list.add(goodsInfo8);
        list.add(goodsInfo9);
        list.add(goodsInfo10);
        list.add(goodsInfo11);
        list.add(goodsInfo12);
        list.add(goodsInfo13);
        return list;
    }

    /**
     * 对获取到的商品信息进行排序
     *
     * @param goodsInfos
     */
    public static List<GoodsInfo> getSortGoods(List<GoodsInfo> goodsInfos) {
        //获取可抢单的商品，且跟据价格由高到底排序
        List<GoodsInfo> goodsInfoList = goodsInfos.stream().filter(GoodsInfo::isUsed).sorted(Comparator.comparing(GoodsInfo::getPrice).reversed()).collect(Collectors.toList());
        return goodsInfoList;
    }

    public static List<UserInfo> getSortUserInfos(List<UserInfo> userInfos) {
        //获取可抢单的商品，且跟据价格由高到底排序
        List<UserInfo> userInfoList = userInfos.stream().filter(UserInfo::isUse).sorted(Comparator.comparing(UserInfo::getMaxPrice).reversed())
                .sorted(Comparator.comparing(UserInfo::getMinPrice).reversed())
                .collect(Collectors.toList());
        return userInfoList;
    }

    private static List<UserInfo> getUserInfos() {
        UserInfo userInfo1 = new UserInfo("1", true, BigDecimal.valueOf(2), BigDecimal.valueOf(3));
        UserInfo userInfo2 = new UserInfo("2", true, BigDecimal.valueOf(2), BigDecimal.valueOf(3));
        UserInfo userInfo3 = new UserInfo("3", true, BigDecimal.valueOf(3), BigDecimal.valueOf(4));
        UserInfo userInfo4 = new UserInfo("4", true, BigDecimal.valueOf(3), BigDecimal.valueOf(4));
        UserInfo userInfo5 = new UserInfo("5", true, BigDecimal.valueOf(4), BigDecimal.valueOf(5));
        UserInfo userInfo6 = new UserInfo("6", true, BigDecimal.valueOf(4), BigDecimal.valueOf(5));
        UserInfo userInfo7 = new UserInfo("7", true, BigDecimal.valueOf(5), BigDecimal.valueOf(6));
        UserInfo userInfo8 = new UserInfo("8", true, BigDecimal.valueOf(6), BigDecimal.valueOf(7));
        UserInfo userInfo9 = new UserInfo("9", true, BigDecimal.valueOf(6), BigDecimal.valueOf(7));
        UserInfo userInfo10 = new UserInfo("10", true, BigDecimal.valueOf(7), BigDecimal.valueOf(8));
        UserInfo userInfo11 = new UserInfo("10", false, BigDecimal.valueOf(7), BigDecimal.valueOf(8));
        List<UserInfo> list = new ArrayList<>();
        list.add(userInfo1);
        list.add(userInfo2);
        list.add(userInfo3);
        list.add(userInfo4);
        list.add(userInfo5);
        list.add(userInfo6);
        list.add(userInfo7);
        list.add(userInfo8);
        list.add(userInfo9);
        list.add(userInfo10);
        list.add(userInfo11);
        return list;
    }


    private static class UserInfo {
        private String id;

        private boolean isUse;

        private BigDecimal minPrice;

        private BigDecimal maxPrice;

        public UserInfo(String id, boolean isUse, BigDecimal minPrice, BigDecimal maxPrice) {
            this.id = id;
            this.isUse = isUse;
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
        }

        public boolean isUse() {
            return isUse;
        }

        public void setUse(boolean use) {
            isUse = use;
        }

        public UserInfo(String id, BigDecimal minPrice, BigDecimal maxPrice) {
            this.id = id;
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public BigDecimal getMinPrice() {
            return minPrice;
        }

        public void setMinPrice(BigDecimal minPrice) {
            this.minPrice = minPrice;
        }

        public BigDecimal getMaxPrice() {
            return maxPrice;
        }

        public void setMaxPrice(BigDecimal maxPrice) {
            this.maxPrice = maxPrice;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "id='" + id + '\'' +
                    ", isUse=" + isUse +
                    ", minPrice=" + minPrice +
                    ", maxPrice=" + maxPrice +
                    '}';
        }
    }


    private static class GoodsInfo {
        private String id;
        private BigDecimal price;
        private boolean isUsed;

        public GoodsInfo(String id, BigDecimal price, boolean isUsed) {
            this.id = id;
            this.price = price;
            this.isUsed = isUsed;
        }

        public boolean isUsed() {
            return isUsed;
        }

        public void setUsed(boolean used) {
            isUsed = used;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public BigDecimal getPrice() {
            return price;
        }

        public void setPrice(BigDecimal price) {
            this.price = price;
        }

        @Override
        public String toString() {
            return "GoodsInfo{" +
                    "id='" + id + '\'' +
                    ", price=" + price +
                    ", isUsed=" + isUsed +
                    '}';
        }
    }
}
